package edu.kit.csl.cratylus.extraction;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import edu.kit.csl.cratylus.datatypes.Candidate;
import edu.kit.csl.cratylus.datatypes.Corpus;
import edu.kit.csl.cratylus.datatypes.SentencePair;
import edu.kit.csl.cratylus.datatypes.SentencePair.AlignmentPair;
import edu.kit.csl.cratylus.datatypes.Word;

/**
 * This planner implementation sorts the source words by the number of target
 * words aligned to them (descending), and then successively sends those sets
 * to the splitter.
 * 
 * @see Planner
 * @see Splitter
 */
public class SourceWordFrequencyPlanner implements Planner {
	
	private Corpus corpus;
	private List<List<Candidate>> subsets;
	
	/**
	 * Sole constructor. Initializes the planner with the corpus over which
	 * should be iterated. Note that this constructor also builds up internal
	 * data structures such as the sorted list of subset and therefore contains
	 * business logic.
	 * 
	 * @param corpus the subjected corpus
	 * @throws NullPointerException is <code>corpus</code> is null
	 */
	public SourceWordFrequencyPlanner(Corpus corpus) {
		this.corpus = corpus;
		buildSubsets();
	}
	
	/*
	 * This method builds the sorted list of subsets over which should be
	 * iterated. 
	 */
	private void buildSubsets() {
		HashMap<Word, List<Candidate>> map = 
				new HashMap<Word, List<Candidate>>();
		for (SentencePair pair : corpus) {
			for (AlignmentPair al : pair) {
				List<Candidate> subset = map.get(al.getSourceWord());
				if (subset == null) {
					subset = new LinkedList<Candidate>();
					map.put(al.getSourceWord(), subset);
				}
				al.getCandidate().getWord().setRelatedWord(al.getSourceWord());
				subset.add(al.getCandidate());
			}
		}
		subsets = new ArrayList<List<Candidate>>();
		subsets.addAll(map.values());
		Collections.sort(subsets, new Comparator<List<Candidate>>() {
			@Override
			public int compare(List<Candidate> arg0, List<Candidate> arg1) {
				return arg1.size() - arg0.size();
			}
		});
	}
	

	/* (non-Javadoc)
	 * @see java.lang.Iterable#iterator()
	 */
	@Override
	public Iterator<List<Candidate>> iterator() {
        return subsets.iterator();
	}
}
